package com.operation.net.scheduledtask;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.operation.net.handler.SysncInterFlow;
import com.operation.net.mapper.*;
import com.operation.net.model.*;
import com.operation.net.service.impl.*;
import com.operation.net.trapCollect.SnmpTrapHandler;
import com.operation.net.util.ListUtil;
import com.operation.net.util.SNMPSessionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;


import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;


/**
 * 基于注解的方式实现多线程定时任务
 * @Configuration 主要用于标记配置类，兼备Component的效果
 * @EnableScheduling 开启定时任务
 * @EnableAsync 开启多线程
 * 需要实现接口 SchedulingConfigurer
 */
@Configuration
@EnableScheduling
@EnableAsync
public class MultithreadScheduleTask {

//    public static final int DEFAULT_VERSION = SnmpConstants.version2c;
//    public static final String DEFAULT_PROTOCOL = "udp";
//    public static final int DEFAULT_PORT = 161;
//    public static final long DEFAULT_TIMEOUT = 3 * 1000L;
//    public static final int DEFAULT_RETRY = 3;
//
//    /**
//     * 创建对象communityTarget
//     *
//     * @param
//     * @param community
//     * @param
//     * @param
//     * @param
//     * @return CommunityTarget
//     */
//    public static CommunityTarget createDefault(String ip, String community) {
//        Address address = GenericAddress.parse(DEFAULT_PROTOCOL + ":" + ip + "/" + DEFAULT_PORT);
//        CommunityTarget target = new CommunityTarget();
//        target.setCommunity(new OctetString(community));
//        target.setAddress(address);
//        target.setVersion(DEFAULT_VERSION);
//        target.setTimeout(DEFAULT_TIMEOUT); // milliseconds
//        target.setRetries(DEFAULT_RETRY);
//        return target;
//    }
//
//    /**
//     * 异步采集信息
//     *
//     * @param ip
//     * @param community
//     * @param oid
//     */
//    public static void snmpAsynWalk(String ip, String community, String oid) {
//        final CommunityTarget target = createDefault(ip, community);
//        Snmp snmp = null;
//        try {
//            System.out.println("----> demo start <----");
//
//
//            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
//            snmp = new Snmp(transport);
//            snmp.listen();
//
//
//            final PDU pdu = new PDU();
//            final OID targetOID = new OID(oid);
//            final CountDownLatch latch = new CountDownLatch(1);
//            pdu.add(new VariableBinding(targetOID));
//            pdu.setType(PDU.GETBULK);
//            pdu.setMaxRepetitions(Integer.MAX_VALUE);
//            pdu.setNonRepeaters(0);
//
//            ResponseListener listener = new ResponseListener() {
//                public void onResponse(ResponseEvent event) {
//                    ((Snmp) event.getSource()).cancel(event.getRequest(), this);
//
//
//                    try {
//                        PDU response = event.getResponse();
//// PDU request = event.getRequest();
//// SystemInfo.out.println("[request]:" + request);
//                        if (response == null) {
//                            System.out.println("[ERROR]: response is null");
//                        } else if (response.getErrorStatus() != 0) {
//                            System.out.println("[ERROR]: response status" + response.getErrorStatus() + " Text:" + response.getErrorStatusText());
//                        } else {
//
//                            VariableBinding vb = response.get(0);
//
//
//                            boolean finished = checkWalkFinished(targetOID, pdu, vb);
//                            if (!finished) {
//                                System.out.println(vb.getOid() + " = " + vb.getVariable());
//                                pdu.setRequestID(new Integer32(0));
//                                pdu.set(0, vb);
//                                ((Snmp) event.getSource()).getNext(pdu, target, null, this);
//                            } else {
//                                System.out.println("SNMP Asyn walk OID value success !");
//                                latch.countDown();
//                            }
//                        }
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                        latch.countDown();
//                    }
//
//
//                }
//            };
//
//
//
//            snmp.getNext(pdu, target, null, listener);
//            System.out.println("pdu 已发送,等到异步处理结果...");
//
//
//            boolean wait = latch.await(30, TimeUnit.SECONDS);
//            System.out.println("latch.await =:" + wait);
//            snmp.close();
//
//
//            System.out.println("----> demo end <----");
//        } catch (Exception e) {
//            e.printStackTrace();
//            System.out.println("SNMP Asyn Walk Exception:" + e);
//        }
//
//
//    }
//
//    private static boolean checkWalkFinished(OID walkOID, PDU pdu, VariableBinding vb) {
//        boolean finished = false;
//        if (pdu.getErrorStatus() != 0) {
//            System.out.println("[true] pdu.getErrorStatus() != 0 ");
//            System.out.println(pdu.getErrorStatusText());
//            finished = true;
//        } else if (vb.getOid() == null) {
//            System.out.println("[true] vb.getOid() == null");
//            finished = true;
//        } else if (vb.getOid().size() < walkOID.size()) {
//            System.out.println("[true] vb.getOid().size() < targetOID.size()");
//            finished = true;
//        } else if (walkOID.leftMostCompare(walkOID.size(), vb.getOid()) != 0) {
//            System.out.println("[true] targetOID.leftMostCompare() != 0");
//            finished = true;
//        } else if (Null.isExceptionSyntax(vb.getVariable().getSyntax())) {
//            System.out.println("[true] Null.isExceptionSyntax(vb.getVariable().getSyntax())");
//            finished = true;
//        } else if (vb.getOid().compareTo(walkOID) <= 0) {
//            System.out.println("[true] vb.getOid().compareTo(walkOID) <= 0 ");
//            finished = true;
//        }
//        return finished;
//

//    }
    @Autowired
    CpuMapper cpuMapper;

    @Autowired
    MemoryMapper memoryMapper;

    @Autowired
    InterFlowService interFlowService;

    @Autowired
    SystemService systemService;

    @Autowired
    ThreadPingSuccess ping;
    @Autowired
    DiagnosisMapper diagnosisMapper;

    @Autowired
    SysncInterFlow sysncInterFlow;
    @Autowired
    DeviceTypeMapper deviceTypeMapper;
    @Autowired
    InterFlowMapper interFlowMapper;

    @Autowired
    ThreadSnmpService snmpService;

    @Autowired
    SystemInfoMapper systemInfoMapper;



    /**
     * 使用 fixedDelay 的方式设置时间间隔为1秒
     * @Async注解开启一个线程
     */
    @Async
    @Scheduled(fixedRate = 5000)
    public void first() throws Exception {
        Cpu cpu = new Cpu();
        Memory memory = new Memory();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        final long GB = 1024 * 1024 * 1024;
        while (true) {
            OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
            String osJson = JSON.toJSONString(operatingSystemMXBean);
            JSONObject jsonObject = JSON.parseObject(osJson);
            double systemCpuLoad = jsonObject.getDouble("systemCpuLoad") * 100;
            Long totalPhysicalMemorySize = jsonObject.getLong("totalPhysicalMemorySize");
            Long freePhysicalMemorySize = jsonObject.getLong("freePhysicalMemorySize");
            double memoryUseRatio = (1.0 * (totalPhysicalMemorySize - freePhysicalMemorySize) / totalPhysicalMemorySize) * 100;

            InetAddress addr = InetAddress.getLocalHost();
            cpu.setCpuRate(twoDecimal(systemCpuLoad));
            cpu.setIp(addr.getHostAddress());
            cpu.setTime(df.format(new Date()));
            cpuMapper.insert(cpu);
            memory.setIp(addr.getHostAddress());
            memory.setMemTotalReal(twoDecimal(totalPhysicalMemorySize));
            memory.setMemAvailReal(twoDecimal(freePhysicalMemorySize));
            memory.setMemRate(twoDecimal(memoryUseRatio));
            memory.setTime(df.format(new Date()));
            memoryMapper.insert(memory);
            Thread.sleep(1000*30);

        }

    }

    public double twoDecimal(double doubleValue) {
        BigDecimal bigDecimal = new BigDecimal(doubleValue).setScale(2, RoundingMode.HALF_UP);
        return bigDecimal.doubleValue();
    }



    @Scheduled(fixedDelay = 1000)
    public void second() throws Exception {

        System.out.println("第二个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());
        String[] oids = {".1.3.6.1.2.1.2.2.1.1"};//接口index
        String[] oids1 = {".1.3.6.1.2.1.2.2.1.2"};//接口描述

        while (true) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:ss:mm");
            List<InterFlow> interFlows = new ArrayList<>();
            InterFlow inter;
            //List<String> actDevice = systemService.getAllActDevice();

            List<String> ips = systemService.getIps();
            List<String> actDevice = ping.receiveConnectSuccess(ips);

            int j=0;
            System.out.println(actDevice);
        for (String ip : actDevice) {
            SNMPSessionUtil snmp = new SNMPSessionUtil(ip, "161", "public", "2");


            System.out.println("第"+j+"个活跃设备已经完成接口采集"+"时间: "+df.format(new Date()));
            ArrayList<String> indexs = snmp.snmpWalk2(oids);
            ArrayList<String> descs = snmp.snmpWalk2(oids1);
            CompletableFuture<List<List<String>>> interFlow = sysncInterFlow.getInterFlow(ip, 3000);//接口出入流量
            CompletableFuture<List<List<String>>> interFlow1 = sysncInterFlow.getinRate(ip, 3000);//接口广播包利用率
            CompletableFuture<List<List<String>>> interFlow2 = sysncInterFlow.getUpLoss(ip, 3000);//接口出入丢包率
            CompletableFuture<List<List<String>>> interFlow3 = sysncInterFlow.getErrorRate(ip, 3000);//接口出入包错误率
            for (int i = 0; i < interFlow.get().get(0).size(); i++) {
                inter = new InterFlow();
                inter.setIp(ip);
                inter.setInFlow(interFlow.get().get(0).get(i));
                inter.setOutFlow(interFlow.get().get(1).get(i));
                inter.setInRate(interFlow1.get().get(0).get(i));
                inter.setOutRate(interFlow1.get().get(1).get(i));
                inter.setInLoss(interFlow2.get().get(0).get(i));
                inter.setOutLoss(interFlow2.get().get(1).get(i));
                inter.setInErrorRate(interFlow3.get().get(0).get(i));
                inter.setOutErrorRate(interFlow3.get().get(1).get(i));
                inter.setIfindex(indexs.get(i).substring(indexs.get(i).lastIndexOf("=")).replace("=", "").trim());
                inter.setInterDescr(descs.get(i).substring(descs.get(i).lastIndexOf("=")).replace("=", "").trim());
                inter.setTime(df.format(new Date()));
                interFlows.add(inter);

            }
            j+=1;
            interFlowMapper.insert(interFlows);

            }
            System.out.println("第二个定时任务完成 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());
            Thread.sleep(1000*10);
        }
    }


    /**
     * ping连通性监测
     */
    @Async
    @Scheduled(fixedRate = 1000)
    public void third() throws Exception {
        while (true) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            List<String> ips = systemService.getIps();
            List<String> list = ping.receiveConnectSuccess(ips);
            List<String> noping = ListUtil.getDiffrent(ips, list);
            for (String ip : list) {
                Diagnosis d = new Diagnosis();
                d.setIp(ip);
                d.setStatus(0);
                d.setPid(5);//ping
                d.setRank("正常");
                d.setTime(df.format(new Date()));
                SystemInfo s=systemInfoMapper.selectStatus1(d.getIp());
                if (s==null) {
                    systemInfoMapper.setSucess(d.getIp(), d.getRank());
                }
            }


            for (String ip : noping) {
                Diagnosis d = new Diagnosis();
                //SystemInfo systemInfo=new SystemInfo();
                String sping = Ping.sping(ip, 2, 1000);
                d.setIp(ip);
                d.setStatus(0);
                d.setPid(5);//ping
                d.setRank("故障");
                d.setTime(df.format(new Date()));
                d.setCause("断路");
                SystemInfo s=systemInfoMapper.selectStatus(d.getIp());
                if (s==null) {
                    diagnosisMapper.insertByDia(d);
                    systemInfoMapper.setError(d.getIp(), d.getRank());
                }

            }

        }
    }
//
//    /**
//     * 能ping通下
//     * 监测snmp连通性
//     */
//    @Async
//    @Scheduled(fixedRate = 1000)
//    public void checkSnmp() throws Exception {
//        while (true) {
//            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//            List<String> ips = systemService.getIps();
//            List<String> list = ping.receiveConnectSuccess(ips);
//            List<String> ckSnmp = snmpService.IsCkSnmp(list);
//            for (String s : ckSnmp) {
//                Diagnosis d = new Diagnosis();
//                d.setIp(s);
//                d.setStatus(0);//未处理
//                d.setPid(6);//snmp
//                d.setTime(df.format(new Date()));
//                d.setRank("故障");
//                d.setCause("可以PING通,SNMP错误");
//                diagnosisMapper.insertByDia(d);
//            }
//        }
//    }

//    @Scheduled(fixedDelay = 1000*10)
//    public void four() throws Exception {
//        while(true) {
//            SnmpTrapHandler handler = new SnmpTrapHandler();
//            handler.SnmpTrapHandler("192.168.237.1", "162");
//            System.out.println("开始执行trap");
//            handler.start();
//        }
//    }


}


